#include <fcntl.h>
#include <limits.h>
#include <stddef.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

#include "json.h"
#include "json_util.h"

#include "zlog.h"
#include "json_func.h"
#include "usr_cfg.h"
#include "json_parse.h"


/*
说明：json_object_get_string_len不包括结束符
*/

static void stat_and_cat(const char *file)
{
	struct stat sb;
	int d = open(file, O_RDONLY);
	if (d < 0)
	{
		printf("FAIL: unable to open %s: %s\n", file, strerror(errno));
		return;
	}
	if (fstat(d, &sb) < 0)
	{
		printf("FAIL: unable to stat %s: %s\n", file, strerror(errno));
		close(d);
		return;
	}
	char *buf = malloc(sb.st_size + 1);
	if (!buf)
	{
		printf("FAIL: unable to allocate memory\n");
		close(d);
		return;
	}
	if (read(d, buf, sb.st_size) < sb.st_size)
	{
		printf("FAIL: unable to read all of %s: %s\n", file, strerror(errno));
		free(buf);
		close(d);
		return;
	}
	buf[sb.st_size] = '\0';
	printf("file[%s], size=%d, contents=%s\n", file, (int)sb.st_size, buf);
	free(buf);
	close(d);
}

static json_object* read_valid_json_cfg_with_fd(const char *srcfile)
{
	char filename[JSON_CONFIG_PATH_MAX];
	(void)snprintf(filename, sizeof(filename), "%s", srcfile);

	int fd = open(filename, O_RDWR, 0);
	if (fd < 0)
	{
		fprintf(stderr, "FAIL: unable to open %s: %s\n", filename, strerror(errno));
		dzlog_error("FAIL: unable to open %s: %s", filename, strerror(errno));
		exit(EXIT_FAILURE);
	}
	assert(NULL == json_object_from_fd_ex(fd, -2));

    (void)lseek(fd, SEEK_SET, 0);
	
	json_object *jso = json_object_from_fd_ex(fd, 10);
	if (jso != NULL) {
		printf("OK: json_object_from_fd_ex(valid_nested.json, 10)=%s\n",
		       json_object_to_json_string_ext(jso, JSON_C_TO_STRING_PRETTY));
	} else {
		fprintf(stderr, "FAIL: unable to parse contents of %s: %s\n", filename,
		        json_util_get_last_err());
		dzlog_error("FAIL: unable to parse contents of %s", filename);
	}

	close(fd);

    return jso;
}



static int system_config_json_parse(json_object *src_json, sys_cfg_info *sys)
{
	int ret = 0;
	char temp_char[25];
	int temp_int;
	float temp_float;

	if (bool_get_by_jso_key(src_json, "debug_cfg") == true)
	{
		sys->debug = ON;
		printf("!!!!!!!!!system debug is on!!!!!!!!!!\n");
	} else {
		sys->debug = OFF;
		printf("!!!!!!!!!system debug is off!!!!!!!!!!\n");
	}

	strlcpy_by_jso_key(src_json, "config_ver", sys->json_cfg_ver, sizeof(sys->json_cfg_ver));
	if (sys->debug == ON)
        printf("sys->json_cfg_ver is %s\n", sys->json_cfg_ver);
	
	strlcpy_by_jso_key(src_json, "config_name", sys->json_cfg_name, sizeof(sys->json_cfg_name));
	if (sys->debug == ON)
        printf("sys->json_cfg_name is %s\n", sys->json_cfg_name);

	strlcpy_by_jso_key(src_json, "rootfs_ver", sys->rootfs_ver, sizeof(sys->rootfs_ver));
	if (sys->debug == ON)
        printf("sys->rootfs_ver is %s\n", sys->rootfs_ver);

	strlcpy_by_jso_key(src_json, "hardware_ver", sys->hardware_ver, sizeof(sys->hardware_ver));
	if (sys->debug == ON)
        printf("sys->hardware_ver is %s\n", sys->hardware_ver);
	
	if (strlcpy_by_jso_key(src_json, "hardware_name", sys->hardware_name, sizeof(sys->hardware_name)) == SUCCESS)
	{
		if (sys->debug == ON)
        	printf("sys->hardware_name is %s\n", sys->hardware_name);
	}

	struct json_object *root_json;
	json_object_object_get_ex(src_json, "sys_cfg", &root_json);
	struct json_object *sys_cfg_json;
	json_object_object_get_ex(root_json, "manufacturer", &sys_cfg_json);

	if (strlcpy_by_jso_key(sys_cfg_json, "name", sys->manufacturer, sizeof(sys->manufacturer)) == SUCCESS)
	{
		if (sys->debug == ON)
        	printf("sys->manufacturer is %s\n", sys->manufacturer);
	}
	
	json_object_object_get_ex(root_json, "device", &sys_cfg_json);
	memset(sys->dev_name, DEFAULT_FILE_FILL_CHAR, sizeof(sys->dev_name));
	if (strlcpy_by_jso_key(sys_cfg_json, "name", sys->dev_name, sizeof(sys->dev_name)) == SUCCESS)
	{
		if (sys->debug == ON)
        	printf("sys->dev_name is %s\n", sys->dev_name);
	}
	
	memset(sys->dev_type, DEFAULT_FILE_FILL_CHAR, sizeof(sys->dev_type));
	if (strlcpy_by_jso_key(sys_cfg_json, "type", sys->dev_type, sizeof(sys->dev_type)) == SUCCESS)
	{
		if (sys->debug == ON)
        	printf("sys->dev_type is %s\n", sys->dev_type);
	}
	
	memset(sys->dev_sn, DEFAULT_FILE_FILL_CHAR, sizeof(sys->dev_sn));
	if (strlcpy_by_jso_key(sys_cfg_json, "sn", sys->dev_sn, sizeof(sys->dev_sn)) == SUCCESS)
	{
		if (sys->debug == ON)
        	printf("sys->dev_sn is %s\n", sys->dev_sn);
	}

	if (strlcpy_by_jso_key(sys_cfg_json, "uuid", temp_char, sizeof(temp_char)) == SUCCESS)
	{	
	    if (strcmp(sys->dev_uuid, temp_char) != 0)			//不相等
    	{
    		json_object_object_add(sys_cfg_json, "uuid", json_object_new_string(sys->dev_uuid));
			ret = ret + 1;
			dzlog_warn("the new value %s of json object \"uuid\" is add", sys->dev_uuid);
	    } else {
			if (sys->debug == ON)
        		printf("sys->dev_uuid is %s\n", sys->dev_uuid);	
	    }
	}

	memset(sys->dev_local, DEFAULT_FILE_FILL_CHAR, sizeof(sys->dev_local));
	if (strlcpy_by_jso_key(sys_cfg_json, "local", sys->dev_local, sizeof(sys->dev_local)) == SUCCESS)
	{
		if (sys->debug == ON)
        	printf("sys->dev_local is %s\n", sys->dev_local);
	}

	json_object_object_get_ex(root_json, "firmware", &sys_cfg_json);
	memset(sys->fw_version, DEFAULT_FILE_FILL_CHAR, sizeof(sys->fw_version));
	if (strlcpy_by_jso_key(sys_cfg_json, "version", sys->fw_version, sizeof(sys->fw_version)) == SUCCESS)
	{
		if (sys->debug == ON)
        	printf("sys->fw_version is %s\n", sys->fw_version);	
	}
	
	json_object_object_get_ex(root_json, "date", &sys_cfg_json);
	memset(sys->fw_date, DEFAULT_FILE_FILL_CHAR, sizeof(sys->fw_date));
	if (strlcpy_by_jso_key(sys_cfg_json, "date", sys->fw_date, sizeof(sys->fw_date)) == SUCCESS)
	{
		if (sys->debug == ON)
        	printf("sys->fw_version is %s\n", sys->fw_version);	
	}

	/*
	if (strlcpy_by_jso_key(root_json, "triger", temp_char, sizeof(temp_char)) == SUCCESS)
	{
		if (strcmp("EXTERNAL", temp_char) == 0)
		{
			sys->trigger = EXTER;
			if (sys->debug == ON)
        		printf("sys->trigger is external\n");
		} else if (strcmp("BDS", temp_char) == 0) {
			sys->trigger = BDS;										
			if (sys->debug == ON)
        		printf("sys->trigger is gps + bds\n");	
		} else {
			sys->trigger = INTER;										
			if (sys->debug == ON)
        		printf("sys->trigger is internal\n");
		}
	}
	*/
	
	sys->trigger = INTER;												//目前只支持内部触发

	sys->samp_freq = int_get_by_jso_key(root_json, "samp_freq");
	if ((sys->samp_freq != 204800) && (sys->samp_freq != 409600)		//采样率必须正确
		&& (sys->samp_freq != 51200) && (sys->samp_freq != 102400))
	{	
		printf("sys->samp_freq %d is error, app exit!!!\n", sys->samp_freq);
		dzlog_error("sys->samp_freq %d is error, app exit!!!", sys->samp_freq);
		exit(EXIT_FAILURE);
	} else {	
		if (sys->debug == ON)
    		printf("sys->samp_freq is %d\n", sys->samp_freq);
	}

	sys->duration = int_get_by_jso_key(root_json, "duration");
	if ((sys->duration != 1) && (sys->duration != 2)					//采集时间必须正确
		&& (sys->duration != 5) && (sys->duration != 10))
	{
		printf("sys->duration %d is over range, set to max value 2\n", sys->duration);
		dzlog_error("sys->duration %d is over range, set to max value 2", sys->duration);
		exit(EXIT_FAILURE);
	} else {
		if (sys->samp_freq == 204800)
		{
			if (sys->duration > 5)
				sys->duration = 5;
			printf("sys->duration %d is over range, set to max value 5\n", sys->duration);
			dzlog_warn("sys->duration %d is over range, set to max value 5", sys->duration);
		} else if (sys->samp_freq == 409600)
		{
			if (sys->duration > 2)
				sys->duration = 2;
			printf("sys->duration %d is over range, set to max value 2\n", sys->duration);
			dzlog_warn("sys->duration %d is over range, set to max value 2", sys->duration);
		}
		if (sys->debug == ON)
			printf("sys->duration is %d\n", sys->duration); 
	}

	if (bool_get_by_jso_key(root_json, "eigen_calc") == true)
	{
		sys->eigen_calc = ON;
		if (sys->debug == ON)
        	printf("sys->eigen_calc is true\n");
	} else {
		sys->eigen_calc = OFF;
		if (sys->debug == ON)
        	printf("sys->eigen_calc is false\n");
	}

	json_object_object_get_ex(root_json, "impact", &sys_cfg_json);
	if (bool_get_by_jso_key(sys_cfg_json, "enable") == true)
	{
		sys->impact_en = ON;
		if (sys->debug == ON)
        	printf("sys->impact_en is true\n");
	} else {
		sys->impact_en = OFF;
		if (sys->debug == ON)
        	printf("sys->impact_en is false\n");
	}

	sys->impact_map = int_get_by_jso_key(sys_cfg_json, "map");
	if ((sys->impact_map != 0) && (sys->impact_map != 1))
	{
		sys->impact_map = 0;
		printf("sys->impact_map %d is error, set default 0\n", sys->impact_map);
		dzlog_warn("sys->impact_map %d is error, set default 0", sys->impact_map);
	} else {
		if (sys->debug == ON)
			printf("sys->impact_map is %d\n", sys->impact_map); 
	}
	
	json_object_object_get_ex(root_json, "order", &sys_cfg_json);
	if (bool_get_by_jso_key(sys_cfg_json, "enable") == true)
	{
		sys->order_en = ON;
		if (sys->debug == ON)
        	printf("sys->order_en is true\n");
	} else {
		sys->order_en = OFF;
		if (sys->debug == ON)
        	printf("sys->order_en is false\n");
	}

	sys->order_map = int_get_by_jso_key(sys_cfg_json, "map");
	if ((sys->order_map != 0) && (sys->order_map != 1))
	{
		sys->order_map = 0;
		printf("sys->order_map %d is error, set default 0\n", sys->order_map);
		dzlog_warn("sys->order_map %d is error, set default 0", sys->order_map);
	} else {
		if (sys->debug == ON)
			printf("sys->order_map is %d\n", sys->order_map); 
	}

	
	temp_int = int_get_by_jso_key(sys_cfg_json, "spd_thrd");
	if (temp_int != FAILURE)
		sys->order_spd_thrd = temp_int;
	/*		目前还没有阶比采集所以先屏蔽，只按照配置记录一下
	switch (sys->samp_freq)
	{
		case 25600 :
			sys->order_spd_thrd = 120;
			break;
		case 51200 :
			sys->order_spd_thrd = 240;
			break;
		case 102400 :
			sys->order_spd_thrd = 480;
			break;
		case 204800 :
			sys->order_spd_thrd = 480;
			break;
		default :
			printf("sys->order_spd_thrd %d is error, app exit!!!\n", sys->order_spd_thrd);
			dzlog_error("sys->order_spd_thrd %d is error, app exit!!!", sys->order_spd_thrd);
			exit(EXIT_FAILURE);
			break;
	}*/
	if (sys->debug == ON)
        printf("sys->order_spd_thrd is %d\n", sys->order_spd_thrd);	

	temp_int = int_get_by_jso_key(root_json, "main_thd_slp");
	if (temp_int != FAILURE)
		sys->man_thd_slp = temp_int;
	if (sys->debug == ON)
    	printf("sys->man_thd_slp is %d\n", sys->man_thd_slp);	

	temp_int = int_get_by_jso_key(root_json, "daq_thd_slp");
	if (temp_int != FAILURE)
		sys->daq_thd_slp = temp_int;
	if (sys->debug == ON)
    	printf("sys->daq_thd_slp is %d\n", sys->daq_thd_slp);

	json_object_object_get_ex(root_json, "socket", &sys_cfg_json);
	if (strlcpy_by_jso_key(sys_cfg_json, "type", temp_char, sizeof(temp_char)) == SUCCESS)
	{	
		if (strcmp("TCP", temp_char) == 0)	//目前只支持TCP
		{
			sys->socket_type = TCP;	
			if (sys->debug == ON)
        		printf("sys->socket_type is TCP\n");
		} else {
			sys->socket_type = TCP;	
        	printf("sys->socket_type is only TCP support\n");
			dzlog_warn("sys->socket_type is only TCP support");
		}
	}
	
	temp_int = int_get_by_jso_key(sys_cfg_json, "port");
	if (temp_int != FAILURE) 
	{
		sys->socket_port = temp_int;
		if (sys->debug == ON)
			printf("sys->socket_port is %d\n", sys->socket_port);
	} else {
		printf("sys->socket_port is used default %d\n", sys->socket_port);
		dzlog_warn("sys->socket_port is used default %d", sys->socket_port);
	}

	json_object_object_get_ex(root_json, "disk", &sys_cfg_json);
	memset((char*)sys->disk_path, DEFAULT_FILE_FILL_CHAR, sizeof(sys->disk_path));
	if (strlcpy_by_jso_key(sys_cfg_json, "path", sys->disk_path, sizeof(sys->disk_path)) == SUCCESS)
	{
		if (sys->debug == ON)
        	printf("sys->disk_path is %s\n", sys->disk_path);	
	} else {
		printf("sys->disk_path is used default %s\n", sys->disk_path);
		dzlog_warn("sys->disk_path is used default %s", sys->disk_path);
	}

	if (bool_get_by_jso_key(sys_cfg_json, "save_data") == true)
	{
		sys->disk_data_save = ON;
		if (sys->debug == ON)
        	printf("sys->data_save is true\n");
	} else {
		sys->disk_data_save = OFF;
		if (sys->debug == ON)
        	printf("sys->data_save is false\n");
	}

	temp_int = int_get_by_jso_key(sys_cfg_json, "save_data_inv");
	if (temp_int != FAILURE)
		sys->disk_data_save_inv = temp_int;
	if (sys->debug == ON)
        printf("sys->disk_data_save_inv is %d\n", sys->disk_data_save_inv);	

	temp_float = (float)double_get_by_jso_key(sys_cfg_json, "warning_thrd");
	if (temp_float != FAILURE)
	{
		if (temp_float < 500)
			sys->disk_warn_thrd = 500;
		else
			sys->disk_warn_thrd = temp_float;
		if (sys->debug == ON)
        	printf("sys->disk_warn_thrd is %f\n", sys->disk_warn_thrd);	
	} else {
		if (sys->debug == ON)
			printf("sys->disk_warn_thrd is used default %f\n", sys->disk_warn_thrd); 
	}

	temp_float = double_get_by_jso_key(sys_cfg_json, "alarm_thrd");
	if (temp_float != FAILURE)
	{
		if (temp_float < 100)
			sys->disk_alarm_thrd = 100;
		else
			sys->disk_alarm_thrd = temp_float;
		if (sys->debug == ON)
        	printf("sys->disk_alarm_thrd is %f\n", sys->disk_alarm_thrd);	
	} else {
		if (sys->debug == ON)
        	printf("sys->disk_alarm_thrd is used default %f\n", sys->disk_alarm_thrd);	
	}

	temp_int = int_get_by_jso_key(sys_cfg_json, "check_inv");
	if (temp_int != FAILURE)
	{
		if (temp_int < 10)
			sys->disk_chk_inv = 10;
		else
			sys->disk_chk_inv = temp_int;
	} else {
		if (sys->debug == ON)
        	printf("sys->disk_chk_inv is used default %d\n", sys->disk_chk_inv);	
	}

	return ret;
}



static void chx_config_json_parse(struct json_object *src_json, sys_cfg_info *sys, chx_cfg_info chx[])
{	
	char temp_char[16];
	float temp_float;
	int temp_int;
	uint8_t length;

	struct json_object *root_json;
	json_object_object_get_ex(src_json, "chx_cfg", &root_json);
	struct json_object *chx_cfg_json;
	json_object_object_get_ex(root_json, "channel_list", &chx_cfg_json);
	struct json_object *chx_cfg_sub_json;
	if (json_object_get_type(chx_cfg_json) == json_type_array)
	{
		length = (uint8_t)json_object_array_length(chx_cfg_json);
		if (length != ACC_CH_TOTAL)
		{
			printf("CHX channel_list %d is mismatch with json_object_array_length %d, app exit!!!\n", ACC_CH_TOTAL, length);
			dzlog_error("CHX channel_list %d is mismatch with json_object_array_length %d, app exit!!!", ACC_CH_TOTAL, length);
			exit(EXIT_FAILURE);
		}
	    for (uint8_t index = 0; index < length; index++)
	    {
	    	chx_cfg_sub_json = json_object_array_get_idx(chx_cfg_json, index);
			if (bool_get_by_jso_key(chx_cfg_sub_json, "enable") == true)
			{
				chx[index].chx_en = ON;
				if (sys->debug == ON)
		        	printf("chx[%d].chx_en is true\n", index);
			} else {
				chx[index].chx_en = OFF;
				if (sys->debug == ON)
		        	printf("chx[%d].chx_en is false\n", index);
			}

			strlcpy_by_jso_key(chx_cfg_sub_json, "manufacturer", chx[index].chx_sensor.manufacturer, 
														sizeof(chx[index].chx_sensor.manufacturer));
			if (sys->debug == ON)
				printf("chx[%d].chx_sens.manufacturer is %s\n", index, chx[index].chx_sensor.manufacturer); 
									
			strlcpy_by_jso_key(chx_cfg_sub_json, "modle", chx[index].chx_sensor.modle, 
														sizeof(chx[index].chx_sensor.modle));
			if (sys->debug == ON)
				printf("chx[%d].chx_sens.modle is %s\n", index, chx[index].chx_sensor.modle); 

			strlcpy_by_jso_key(chx_cfg_sub_json, "sn", chx[index].chx_sensor.sn, sizeof(chx[index].chx_sensor.sn));
			if (sys->debug == ON)
				printf("chx[%d].chx_sens.sn is %s\n", index, chx[index].chx_sensor.sn); 
			
			strlcpy_by_jso_key(chx_cfg_sub_json, "type", chx[index].chx_sensor.type, sizeof(chx[index].chx_sensor.type));
			if (sys->debug == ON)
				printf("chx[%d].chx_sens.type is %s\n", index, chx[index].chx_sensor.type); 

			strlcpy_by_jso_key(chx_cfg_sub_json, "unit", chx[index].chx_sensor.unit, sizeof(chx[index].chx_sensor.unit));
			if (sys->debug == ON)
				printf("chx[%d].chx_sens.unit is %s\n", index, chx[index].chx_sensor.unit); 
			
			strlcpy_by_jso_key(chx_cfg_sub_json, "range", chx[index].chx_sensor.range, sizeof(chx[index].chx_sensor.range));
			if (sys->debug == ON)
				printf("chx[%d].chx_sens.range is %s\n", index, chx[index].chx_sensor.range); 
			
			strlcpy_by_jso_key(chx_cfg_sub_json, "desc", chx[index].chx_desc, sizeof(chx[index].chx_desc));
			if (sys->debug == ON)
				printf("chx[%d].chx_desc is %s\n", index, chx[index].chx_desc); 
			
			temp_int = int_get_by_jso_key(chx_cfg_sub_json, "samp_freq");
			if (temp_int != FAILURE)
			{
				chx[index].chx_sample_freq = temp_int;
				if ((chx[index].chx_sample_freq != 204800) && (chx[index].chx_sample_freq != 25600)
					&& (chx[index].chx_sample_freq != 51200) && (chx[index].chx_sample_freq != 102400)
					&& (chx[index].chx_sample_freq != 409600))
				{	
					printf("chx[%d].chx_sample_freq %d is error, app exit!!!\n", index, chx[index].chx_sample_freq);
					dzlog_error("chx[%d].chx_sample_freq %d is error, app exit!!!", index, chx[index].chx_sample_freq);
					exit(EXIT_FAILURE);
				} else if (sys->debug == ON)
					printf("chx[%d].chx_sample_freq is %d\n", index, chx->chx_sample_freq); 	
			} else {
				printf("chx[%d].chx_sample_freq %d is error, app exit!!!\n", index, chx[index].chx_sample_freq);
				dzlog_error("chx[%d].chx_sample_freq %d is error, app exit!!!", index, chx[index].chx_sample_freq);
				exit(EXIT_FAILURE);
			}

			if (strlcpy_by_jso_key(chx_cfg_sub_json, "mode", temp_char, sizeof(temp_char)) == SUCCESS)
			{
				if (strcmp("AC", temp_char) == 0)
				{
					chx[index].chx_mode = AC;
					if (sys->debug == ON)
						printf("chx[%d].chx_mode is AC\n", index); 
				} else if (strcmp("DC", temp_char) == 0) {
					chx[index].chx_mode = DC;
					if (sys->debug == ON)
						printf("chx[%d].chx_mode is DC\n", index); 
				} else if (strcmp("IEPE", temp_char) == 0) {
					chx[index].chx_mode = IEPE;
					if (sys->debug == ON)
						printf("chx[%d].chx_mode is IEPE\n", index); 
				} else if (strcmp("TIB", temp_char) == 0) {
					chx[index].chx_mode = TIB;
					if (sys->debug == ON)
						printf("chx[%d].chx_mode is TIB\n", index); 
				} else if (strcmp("CAL", temp_char) == 0) {
					chx[index].chx_mode = CAL;
					if (sys->debug == ON)
						printf("chx[%d].chx_mode is CAL\n", index); 
				} else {
					chx[index].chx_mode = SAFE;
					if (sys->debug == ON)
						printf("chx[%d].chx_mode is SAFE\n", index); 
				}
			}else {
				printf("chx[%d].chx_mode %d is error, app exit!!!\n", index, chx[index].chx_mode);
				dzlog_error("chx[%d].chx_mode %d is error, app exit!!!", index, chx[index].chx_mode);
				exit(EXIT_FAILURE);
			}

			temp_float = (float)double_get_by_jso_key(chx_cfg_sub_json, "pga_gain");
			if (temp_float != FAILURE)
			{
				chx[index].chx_pga_gain = temp_float;
				if (chx[index].chx_pga_gain == 0.0f)
					chx[index].chx_pga_gain = 0.00001f;
				if (sys->debug == ON)
					printf("chx[%d].chx_pga_gain is %f\n", index, chx[index].chx_pga_gain); 
			} else {
				chx[index].chx_pga_gain = 1.0f;
				printf("chx[%d].chx_pga_gain %f is error, used gain 1.0\n", index, chx[index].chx_pga_gain); 
				dzlog_error("chx[%d].chx_pga_gain %f is error, used gain 1.0", index, chx[index].chx_pga_gain);
			}

			temp_float = (float)double_get_by_jso_key(chx_cfg_sub_json, "drcc_gain");
			if (temp_float != FAILURE)
			{
				chx[index].chx_drcc_gain = temp_float;
				if (chx[index].chx_drcc_gain == 0.0f)
					chx[index].chx_drcc_gain = 0.00001f;
				if (sys->debug == ON)
					printf("chx[%d].chx_drcc_gain is %f\n", index, chx[index].chx_drcc_gain); 
			} else {
				chx[index].chx_drcc_gain = 1.0f;
				printf("chx[%d].chx_drcc_gain %f is error, used gain 1.0\n", index, chx[index].chx_drcc_gain); 
				dzlog_error("chx[%d].chx_drcc_gain %f is error, used gain 1.0", index, chx[index].chx_drcc_gain);
			}

			
			temp_float = (float)double_get_by_jso_key(chx_cfg_sub_json, "sens");
			if (temp_float != FAILURE)
			{
				chx[index].chx_sens = temp_float;
				if (chx[index].chx_sens == 0.0f)
					chx[index].chx_sens = 0.00001f;
				if (sys->debug == ON)
					printf("chx[%d].chx_sens is %f\n", index, chx[index].chx_sens); 
			} else {
				chx[index].chx_sens = 1.0f;
				printf("chx[%d].chx_sens %f is error, used snes 1.0\n", index, chx[index].chx_sens); 
				dzlog_error("chx[%d].chx_sens %f is error, used snes 1.0", index, chx[index].chx_sens);
			}

			if (strlcpy_by_jso_key(chx_cfg_sub_json, "windows", temp_char, sizeof(temp_char)) == SUCCESS)
			{
				if (strcmp("RECT", temp_char) == 0)
				{
					chx[index].chx_win_func = RECT;
					if (sys->debug == ON)
						printf("chx[%d].chx_win_func is RECT\n", index); 
				} else if (strcmp("HANN", temp_char) == 0)
				{
					chx[index].chx_win_func = HANN;
					if (sys->debug == ON)
						printf("chx[%d].chx_win_func is HANN\n", index); 
				} else if (strcmp("HAMM", temp_char) == 0)
				{
					chx[index].chx_win_func = HAMM;
					if (sys->debug == ON)
						printf("chx[%d].chx_win_func is HAMM\n", index); 
				} else 
				{	
					chx[index].chx_win_func = RECT;
					if (sys->debug == ON)
						printf("chx[%d].chx_win_func is RECT\n", index); 
				}
			}else {
				chx[index].chx_win_func = RECT;
				printf("chx[%d].chx_win_func is used default RECT\n", index); 
				dzlog_warn("chx[%d].chx_win_func is used default RECT", index);
			}

			temp_float = (float)double_get_by_jso_key(chx_cfg_sub_json, "offset");
			if (temp_float != FAILURE)
			{
				chx[index].chx_offset = temp_float;
				if (sys->debug == ON)
					printf("chx[%d].chx_offset is %f\n", index, chx[index].chx_offset); 
			} else {
				chx[index].chx_offset = 0.0f;
				printf("chx[%d].chx_offset is used default 0.0f\n", index); 
				dzlog_warn("chx[%d].chx_offset is used default 0.0f", index);
			}

			temp_float = (float)double_get_by_jso_key(chx_cfg_sub_json, "warning");
			if (temp_float != FAILURE)
			{
				chx[index].chx_warning = temp_float;
			}
			if (sys->debug == ON)
				printf("chx[%d].chx_warning is %f\n", index, chx[index].chx_warning); 

			temp_float = (float)double_get_by_jso_key(chx_cfg_sub_json, "alarm");
			if (temp_float != FAILURE)
			{
				chx[index].chx_alarm = temp_float;
			}
			if (sys->debug == ON)
				printf("chx[%d].chx_alarm is %f\n", index, chx[index].chx_alarm); 
		}
	}
}



static void speed_config_json_parse(struct json_object *src_json, sys_cfg_info *sys, spd_cfg_info spd[])
{
	char temp_char[16];
	float temp_float;
	uint8_t length;

	struct json_object *root_json;
	json_object_object_get_ex(src_json, "spd_cfg", &root_json);
	struct json_object *spd_cfg_json;
	json_object_object_get_ex(root_json, "channel_list", &spd_cfg_json);
	struct json_object *spd_cfg_sub_json;
	if (json_object_get_type(spd_cfg_json) == json_type_array)
	{
		length = (uint8_t)json_object_array_length(spd_cfg_json);
		if (length != SPD_CH_TOTAL)
		{
			printf("SPD channel_list %d is mismatch with json_object_array_length %d, app exit!!!\n", SPD_CH_TOTAL, length);
			dzlog_error("SPD channel_list %d is mismatch with json_object_array_length %d, app exit!!!", SPD_CH_TOTAL, length);
			exit(EXIT_FAILURE);
		}
	    for (uint8_t index = 0; index < length; index++)
	    {
	    	spd_cfg_sub_json = json_object_array_get_idx(spd_cfg_json, index);
			if (bool_get_by_jso_key(spd_cfg_sub_json, "enable") == true)
			{
				spd[index].spd_en = ON;
				if (sys->debug == ON)
					printf("spd[%d].spd_en is true\n", index);
			} else {
		    	spd[index].spd_en = OFF;
				if (sys->debug == ON)
		        	printf("spd[%d].spd_en is false\n", index);
			}			

			strlcpy_by_jso_key(spd_cfg_sub_json, "manufacturer", spd[index].spd_sensor.manufacturer, 
														sizeof(spd[index].spd_sensor.manufacturer));
			if (sys->debug == ON)
				printf("spd[%d].spd_sens.manufacturer is %s\n", index, spd[index].spd_sensor.manufacturer);
			
			strlcpy_by_jso_key(spd_cfg_sub_json, "modle", spd[index].spd_sensor.modle, 
														sizeof(spd[index].spd_sensor.modle));
			if (sys->debug == ON)
				printf("spd[%d].spd_sens.modle is %s\n", index, spd[index].spd_sensor.modle); 

			strlcpy_by_jso_key(spd_cfg_sub_json, "sn", spd[index].spd_sensor.sn, sizeof(spd[index].spd_sensor.sn));
			if (sys->debug == ON)
				printf("spd[%d].spd_sens.sn is %s\n", index, spd[index].spd_sensor.sn); 

			strlcpy_by_jso_key(spd_cfg_sub_json, "range", spd[index].spd_sensor.range, sizeof(spd[index].spd_sensor.range));
			if (sys->debug == ON)
				printf("spd[%d].spd_sens.range is %s\n", index, spd[index].spd_sensor.range); 

			strlcpy_by_jso_key(spd_cfg_sub_json, "desc", spd[index].spd_desc, sizeof(spd[index].spd_desc));
			if (sys->debug == ON)
				printf("spd[%d].spd_desc is %s\n", index, spd[index].spd_desc); 

			if (strlcpy_by_jso_key(spd_cfg_sub_json, "mode", temp_char, sizeof(temp_char)) == SUCCESS)
			{
				if (strcmp("PHOTO", temp_char) == 0)
				{
					spd[index].spd_mode = PHOTO;
					if (sys->debug == ON)
						printf("spd[%d].spd_mode is PHOTO\n", index);
				} else if (strcmp("MAGN", temp_char) == 0)
				{
					spd[index].spd_mode = MAGN;
					if (sys->debug == ON)
						printf("spd[%d].spd_mode is MAGN\n", index);
				} else if (strcmp("PLUSE", temp_char) == 0)
				{
					spd[index].spd_mode = PLUSE;
					if (sys->debug == ON)
						printf("spd[%d].spd_mode is PLUSE\n", index);
				} else if (strcmp("CLOSE", temp_char) == 0)
				{
					spd[index].spd_mode = CLOSE;
					if (sys->debug == ON)
						printf("spd[%d].spd_mode is CLOSE\n", index);
				} else
				{
					printf("spd[%d].spd_mode %d is error, app exit!!!\n", index, spd[index].spd_mode);
					dzlog_error("spd[%d].spd_mode %d is error, app exit!!!", index, spd[index].spd_mode);
					exit(EXIT_FAILURE);
				}
			} else {
				printf("spd[%d].spd_mode %d is error, app exit!!!\n", index, spd[index].spd_mode);
				dzlog_error("spd[%d].spd_mode %d is error, app exit!!!", index, spd[index].spd_mode);
				exit(EXIT_FAILURE);
			}

			if (strlcpy_by_jso_key(spd_cfg_sub_json, "mode", temp_char, sizeof(temp_char)) == SUCCESS)
			{
				if (strcmp("DIRECT", temp_char) == 0)
				{
					spd[index].spd_calc = DIRECT;
					if (sys->debug == ON)
						printf("spd[%d].spd_calc is DIRECT\n", index);
				} else if (strcmp("FREQ", temp_char) == 0)
				{
					spd[index].spd_calc = FREQ;
					if (sys->debug == ON)
						printf("spd[%d].spd_calc is FREQ\n", index);
				} else if (strcmp("MVAVG", temp_char) == 0)
				{
					spd[index].spd_calc = MVAVG;
					if (sys->debug == ON)
						printf("spd[%d].spd_calc is MVAVG\n", index);
				} else if (strcmp("YMVCUT", temp_char) == 0)
				{
					spd[index].spd_calc = YMVCUT;
					if (sys->debug == ON)
						printf("spd[%d].spd_calc is YMVCUT\n", index);
				} else
				{
					spd[index].spd_calc = DIRECT;
					printf("spd[%d].spd_mode is used default DIRECT\n", index);
					dzlog_warn("spd[%d].spd_mode used default DIRECT", index);
				}
			} else {
				spd[index].spd_calc = DIRECT;
				printf("spd[%d].spd_mode is used default DIRECT\n", index);
				dzlog_warn("spd[%d].spd_mode used default DIRECT", index);
			}

			temp_float = double_get_by_jso_key(spd_cfg_sub_json, "pulse");
			if (temp_float != FAILURE)
			{
				spd[index].spd_pulse = temp_float;
				if ((spd[index].spd_pulse == 0.0f) || (spd[index].spd_pulse > 9.99f))
					spd[index].spd_pulse = 1.0f;
				if (sys->debug == ON)
					printf("spd[%d].spd_pulse is %f\n", index, spd[index].spd_pulse); 
			} else {
				spd[index].spd_pulse = 1.0f;
				printf("spd[%d].spd_pulse is used default 1\n", index); 
				dzlog_warn("spd[%d].spd_pulse is used default 1", index);
			}

			temp_float = (float)double_get_by_jso_key(spd_cfg_sub_json, "threshold");
			if (temp_float != FAILURE)
			{
				spd[index].spd_save_thrd = temp_float;
				if (spd[index].spd_save_thrd < 60.0f)
					spd[index].spd_save_thrd = 60.0f;
				if (sys->debug == ON)
					printf("spd[%d].spd_save_thrd is %f\n", index, spd[index].spd_save_thrd); 
			} else {
				spd[index].spd_save_thrd = 60.0f;
				printf("spd[%d].spd_save_thrd is used default 60.0f\n", index); 
				dzlog_warn("spd[%d].spd_save_thrd is used default 60.0f", index);
			}
	    }
	}
}


static void rs485_config_json_parse(struct json_object *src_json, sys_cfg_info *sys, rs485_cfg_info *rs485)
{
	char temp_char[16];
	uint8_t temp_int;

	struct json_object *root_json;
	json_object_object_get_ex(src_json, "rs485_cfg", &root_json);

	if (bool_get_by_jso_key(root_json, "enable") == true)
	{
		rs485->rs485_en = ON;
		if (sys->debug == ON)
			printf("rs485->rs485_en is true\n");
	} else {
		rs485->rs485_en = OFF;
		if (sys->debug == ON)
			printf("rs485->rs485_en is false\n");
	}

	strlcpy_by_jso_key(root_json, "mode", temp_char, sizeof(temp_char));
	strcpy(rs485->rs485_mode, "server");					//目前只支持server模式
	if (sys->debug == ON)
		printf("rs485->rs485_mode is %s\n", rs485->rs485_mode);

	if (bool_get_by_jso_key(root_json, "modbus") == true)
	{
		rs485->rs485_modbus_en = ON;
		if (sys->debug == ON)
			printf("rs485->rs485_modbus_en is true\n");
	} else {
		rs485->rs485_modbus_en = OFF;
		if (sys->debug == ON)
			printf("rs485->rs485_modbus_en is false\n");
	}

	temp_int = (uint8_t)int_get_by_jso_key(root_json, "dev_id");
	if (temp_int != FAILURE)
	{
		if ((temp_int > 0) && (temp_int < 248))				// 1 到 247 之间
			rs485->rs485_dev_id = temp_int;
		else
			rs485->rs485_dev_id = 1;
		if (sys->debug == ON)
			printf("rs485->rs485_dev_id is %d\n", rs485->rs485_dev_id);
	} else {
		rs485->rs485_dev_id = 1;
		printf("rs485->rs485_dev_id is used default 1\n");
		dzlog_warn("rs485->rs485_dev_id is used default 1");
	}

	strlcpy_by_jso_key(root_json, "com", temp_char, sizeof(temp_char));
	strcpy(rs485->rs485_uart_cfg.com, "ttyS2");					//固定值，不能修改
	if (sys->debug == ON)
		printf("rs485->rs485_uart_cfg.com is %s\n", rs485->rs485_uart_cfg.com);

	if (strlcpy_by_jso_key(root_json, "baudrate", temp_char, sizeof(temp_char)) == SUCCESS)
	{
		if (strcmp("B4800", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.baudrate = B4800BPS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.baudrate is b4800bps\n");
		} else if (strcmp("B9600", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.baudrate = B9600BPS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.baudrate is b9600bps\n");
		} else if (strcmp("B19200", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.baudrate = B19200BPS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.baudrate is b19200bps\n");
		} else if (strcmp("B38400", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.baudrate = B38400BPS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.baudrate is b38400bps\n");
		} else if (strcmp("B57600", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.baudrate = B57600BPS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.baudrate is b57600bps\n");
		} else if (strcmp("B115200", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.baudrate = B115200BPS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.baudrate is b115200bps\n");
		} else
		{
			rs485->rs485_uart_cfg.baudrate = B9600BPS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.baudrate is default b9600bps\n");
		}
	}else {
		rs485->rs485_uart_cfg.baudrate = B9600BPS;
		printf("rs485->rs485_uart_cfg.baudrate is used default b9600bps\n");
		dzlog_warn("rs485->rs485_uart_cfg.baudrate is used default b9600bps");
	}

	if (strlcpy_by_jso_key(root_json, "bits", temp_char, sizeof(temp_char)) == SUCCESS)
	{
		if (strcmp("7", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.bits = DATA_7BITS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.bits is 7 bits\n");
		} else if (strcmp("8", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.bits = DATA_8BITS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.bits is 8 bits\n");
		} else 
		{
			rs485->rs485_uart_cfg.bits = DATA_8BITS;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.bits is default 8 bits\n");
		}
	} else {
		rs485->rs485_uart_cfg.bits = DATA_8BITS;
		printf("rs485->rs485_uart_cfg.bits is used default 8 bits\n");
		dzlog_warn("rs485->rs485_uart_cfg.bits is used default 8 bits");
	}

	if (strlcpy_by_jso_key(root_json, "parity", temp_char, sizeof(temp_char)) == SUCCESS)
	{
		if (strcmp("NONE", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.parity = NONE;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.parity is none\n");
		} else if (strcmp("ODD", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.parity = ODD;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.parity is odd\n");
		} else if (strcmp("EVEN", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.parity = EVEN;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.parity is even\n");
		} else
		{
			rs485->rs485_uart_cfg.parity = NONE;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.parity is default none\n");
		}
	} else {
		rs485->rs485_uart_cfg.parity = NONE;
		printf("rs485->rs485_uart_cfg.parity is used default none\n");
		dzlog_warn("rs485->rs485_uart_cfg.parity is used default none");
	}

	if (strlcpy_by_jso_key(root_json, "stop", temp_char, sizeof(temp_char)) == SUCCESS)
	{
		if (strcmp("1", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.stop = STOP_1BIT;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.stop is 1 bit\n");
		} else if (strcmp("2", temp_char) == 0)
		{
			rs485->rs485_uart_cfg.stop = STOP_2BIT;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.stop is 2 bit\n");
		} else
		{
			rs485->rs485_uart_cfg.stop = STOP_1BIT;
			if (sys->debug == ON)
				printf("rs485->rs485_uart_cfg.stop is default 1 bit\n");
		}	
	} else {
		rs485->rs485_uart_cfg.stop = STOP_1BIT;
		printf("rs485->rs485_uart_cfg.stop is used default 1bit\n");
		dzlog_warn("rs485->rs485_uart_cfg.stop is used default 1bit");	
	}
}


int system_config_file_json_parse(sys_cfg_info *sys, chx_cfg_info chx[], 
												spd_cfg_info spd[], rs485_cfg_info *rs485)
{
	const char *srcfile = JSON_CONFIG_FILE;
	int rw = 0;

	if (strncmp(json_c_version(), JSON_C_VERSION, sizeof(JSON_C_VERSION)))
	{
		printf("FAIL: Output from json_c_version(): %s "
		       "does not match %s",
		       json_c_version(), JSON_C_VERSION);
		return EXIT_FAILURE;
	}
	if (json_c_version_num() != JSON_C_VERSION_NUM)
	{
		printf("FAIL: Output from json_c_version_num(): %d "
		       "does not match %d",
		       json_c_version_num(), JSON_C_VERSION_NUM);
		return EXIT_FAILURE;
	}
	
    struct json_object *src_json;
	src_json = read_valid_json_cfg_with_fd(srcfile);

	rw = system_config_json_parse(src_json, sys);
	chx_config_json_parse(src_json, sys, chx);
	speed_config_json_parse(src_json, sys, spd);
	rs485_config_json_parse(src_json, sys, rs485);

	if (rw != 0) {
		int rv =  json_object_to_file_ext(srcfile, src_json, JSON_C_TO_STRING_PRETTY);
		printf("%s: json_object_to_file(%s, jso)=%d\n", (rv == 0) ? "OK" : "FAIL", srcfile, rv);
		if (rv == 0)
			stat_and_cat(srcfile);
	}

	json_object_put(src_json);

	return SUCCESS;
}


